﻿using learun.util;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Nacos.AspNetCore;
using NLog;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Assets.API
{
    public class JwtAuthorizeMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IOperator _operator;

        internal Logger _logger = LogManager.GetCurrentClassLogger();

        //添加Nacos 中间件
        private readonly INacosServerManager _serverManager;
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="next">请求委托</param>
        /// <param name="ioperator">验证登录信息方法</param>
        public JwtAuthorizeMiddleware(RequestDelegate next, IOperator ioperator, INacosServerManager iserverManager)
        {
            _next = next;
            _operator = ioperator;
            _serverManager = iserverManager;
        }

        /// <summary>
        ///SQL注入过滤
        /// </summary>
        /// <param name="InText">要过滤的字符串</param>
        /// <returns>如果参数存在不安全字符，则返回true</returns>
        public static bool SqlFilter2(string InText)
        {
            string word = ConfigHelper.GetConfig().RequestForbidWord;
            if (InText == null || InText== "?org" || InText== "orgname" || InText=="org")
                return false;
            foreach (string i in word.Split('|'))
            {
                if ((InText.ToLower().IndexOf(i + " ") > -1) || (InText.ToLower().IndexOf(" " + i) > -1)
                     || (InText.ToLower().IndexOf(i) > -1)
                    )
                {
                    return true;
                }
            }
            return false;
        }
        //// <summary>
        /// 校验参数是否存在SQL字符
        /// </summary>
        /// <param name="tm"></param>
        private void goErr(string tm)
        {
            //string Errorpage = ConfigurationManager.AppSettings["SqlErrorpage"].ToString();
            if (SqlFilter2(tm))
            {
                ///return Fail("输入的参数不合法");
                Exception exception = new Exception();
                throw exception;
            }
        }
        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="httpContext">请求连接</param>
        /// <returns></returns>
        public async Task Invoke(HttpContext httpContext)
        {
            //string url = SetUrl(httpContext);
            //endpoint.DisplayName "{documentName}/api-docs HTTP: GET"
            //防止sql注入
            if (httpContext.Request.Method.ToLower() == "get")
            {
                string bosy = httpContext.Request.QueryString.Value;
                foreach (string s in bosy.Split('&'))
                {
                    _logger.Info(s);
                    if (s != "")
                    {
                        _logger.Info(s.Substring(s.LastIndexOf("=") + 1));
                        if (SqlFilter2(s.Substring(s.LastIndexOf("=") + 1)))
                        {
                            await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.exception, message = "输入参数不合法" });
                            return;
                        }
                    }
                }
            }
            var endpoint = httpContext.GetEndpoint();
            if (endpoint != null && endpoint.DisplayName != "{documentName}/api-docs HTTP: GET" && endpoint.Metadata.GetMetadata<IAllowAnonymous>() == null)
            {
                // 获取请求值
                //if (!httpContext.Request.Headers["token"].IsEmpty())
                if (!httpContext.Request.Headers["Authorization"].IsEmpty())
                {
                    //string token = httpContext.Request.Headers["token"].ToString();
                    string token = httpContext.Request.Headers["Authorization"].ToString();

                    if (!token.StartsWith("Bearer ") && !token.StartsWith("bearer "))
                    {
                        await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, message = "Authorization 格式有误" });
                        return;
                    }

                    token = token.ToString().Substring("Bearer ".Length).Trim();
                    //token = token.ToString().Substring("bearer ".Length).Trim();


                    //HttpRequest
                    //var res = _operator.DecodeToken(token);
                    //if (res == "TokenExpiredException")
                    //{
                    //    await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, info = "登录信息过期" });
                    //    return;
                    //}
                    //else if (res == "SignatureVerificationException")
                    //{
                    //    await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, info = "非法密钥" });
                    //    return;
                    //}
                    //else
                    //{
                    //    var payload = res.ToObject<Payload>();
                    //    ContextHelper.SetItem("account", payload.Account);
                    //    ContextHelper.SetItem("userId", payload.UserId);
                    //    ContextHelper.SetItem("userName", payload.UserName);
                    //}


                    #region 大三资权限判断
                    //edit by xdl 202011
                    var baseUrl = _serverManager.GetServerAsync("ic-auth").GetAwaiter().GetResult();

                    if (string.IsNullOrWhiteSpace(baseUrl))
                    {
                        await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.exception, message = "授权服务节点全挂了" });
                        return;
                    }

                    //var url = $"{baseUrl}/oauth/check_token";
                    //http://{{BASE_URL}}/auth/oauth/token?grant_type=password

                    var url = $"{baseUrl}/oauth/check_token";

                    using (HttpClient client = new HttpClient())
                    {
                        string clientInfo = "test:test";
                        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(clientInfo);
                        clientInfo = Convert.ToBase64String(bytes, Base64FormattingOptions.None);

                        client.DefaultRequestHeaders.Add("Authorization", "Basic " + clientInfo);
                        //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));//ACCEPT header
                        //client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;");

                        //http://118.190.140.38:3000/token/login
                        //url = url.Replace("172.31.162.64:3000", "118.190.140.38:3000");
                        url = BusinessRule.JavaApi.GetIpAddress1(baseUrl);

                        _logger.Trace("url:" + url);


                        //client.BaseAddress = new Uri(url);
                        //设置请求体中的内容，并以post的方式请求
                        //token=697d2737-fe50-49b2-82c8-33ff2932d28a
                        //var response = await client.PostAsync(url, new StringContent("token=697d2737-fe50-49b2-82c8-33ff2932d28a"));

                        var data = Encoding.UTF8.GetBytes("token=" + token);
                        var content = new ByteArrayContent(data);
                        content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");

                        var response = await client.PostAsync(url, content);


                        //获取请求到数据，并转化为字符串
                        var result = response.Content.ReadAsStringAsync().Result;

                        _logger.Trace("sssssssssss:" + result);

                        var Jresult = Newtonsoft.Json.JsonConvert.DeserializeObject<AuthRoot>(result);// result.ToJson();

                        //if (!string.IsNullOrWhiteSpace(Jresult.error))
                        //{
                        //    await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, message = Jresult.error_description });
                        //    return;
                        //}

                        if (null == Jresult.user_info)
                        {
                            await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, message = "没有用户信息" });//Jresult.error_description
                            return;
                        }

                        //var payload = res.ToObject<Payload>();
                        ContextHelper.SetItem("account", Jresult.user_info.username.ToString());
                        ContextHelper.SetItem("userId", Jresult.user_info.id.ToString());
                        ContextHelper.SetItem("userName", Jresult.user_info.realName);

                        ContextHelper.SetItem("deptId", Jresult.user_info.deptId);

                        ContextHelper.SetItem("deptName", Jresult.user_info.deptName);
                        //return Success(Jresult["user_info"]);

                        #region  功能权限
                        var authorizeAttributes = endpoint.Metadata.GetMetadata<XMZCAuthorizeAttribute>();
                        if (null != authorizeAttributes)
                        {
                            string[] strFunction = authorizeAttributes.Function;
                            if (null != strFunction && strFunction.Length > 0)
                            {
                                if (null != Jresult.authorities)
                                {
                                    bool authority = false;
                                    for (int i = 0; i < Jresult.authorities.Count; i++)
                                    {
                                        for (int d = 0; d < strFunction.Length; d++)
                                        {
                                            if (Jresult.authorities[i].ToLower() == strFunction[d].ToLower())
                                            {
                                                authority = true;
                                                break;
                                            }
                                        }
                                    }

                                    if (!authority)
                                    {
                                        await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.noauthority, message = "没有操作权限" });//Jresult.error_description
                                        return;
                                    }
                                }
                            }
                            else
                            {

                            }
                        }
                        #endregion
                    }

                    #endregion

                }
                else
                {
                    await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, message = "权限验证失败" });
                    return;
                }
                
            }
            else
            {
                if (httpContext.Request.Query.ContainsKey("apiccount"))
                {
                    string account = httpContext.Request.Query["apiccount"];
                    ContextHelper.SetItem("account", account);
                }
            }
            
            await _next(httpContext);
            return;
        }

        public async Task GetTokenVAil(HttpContext httpContext, string token)
        {
            var baseUrl = _serverManager.GetServerAsync("ic-auth").GetAwaiter().GetResult(); ;

            if (string.IsNullOrWhiteSpace(baseUrl))
            {
                await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.exception, message = "授权服务节点全挂了" });
                return;
            }

            //var url = $"{baseUrl}/oauth/check_token";
            //http://{{BASE_URL}}/auth/oauth/token?grant_type=password

            var url = $"{baseUrl}/oauth/check_token";

            using (HttpClient client = new HttpClient())
            {
                string clientInfo = "test:test";
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(clientInfo);
                clientInfo = Convert.ToBase64String(bytes, Base64FormattingOptions.None);

                client.DefaultRequestHeaders.Add("Authorization", "Basic " + clientInfo);
                //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));//ACCEPT header
                //client.DefaultRequestHeaders.Add("Accept-Language", "zh-CN,zh;");

                //http://{{BASE_URL}}/auth/oauth/token?grant_type=password
                //http://{{BASE_URL}}/oauth/check_token
                //http://118.190.140.38:3000/token/login

                url = url.Replace("172.31.162.64:3000", "118.190.140.38:3000");
                //client.BaseAddress = new Uri(url);
                //设置请求体中的内容，并以post的方式请求
                //token=697d2737-fe50-49b2-82c8-33ff2932d28a
                //var response = await client.PostAsync(url, new StringContent("token=697d2737-fe50-49b2-82c8-33ff2932d28a"));

                var data = Encoding.UTF8.GetBytes("token=" + token);
                var content = new ByteArrayContent(data);
                content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");

                var response = await client.PostAsync(url, content);


                //获取请求到数据，并转化为字符串
                var result = response.Content.ReadAsStringAsync().Result;
                var Jresult = Newtonsoft.Json.JsonConvert.DeserializeObject<AuthRoot>(result);// result.ToJson();

                //if (!string.IsNullOrWhiteSpace(Jresult.error))
                //{
                //    await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, message = Jresult.error_description });
                //    return;
                //}

                if (null == Jresult.user_info)
                {
                    await RespondWithJson(httpContext.Response, new ResParameter { code = ResponseCode.nologin, message = "没有用户信息" });//Jresult.error_description
                    return;
                }

                //var payload = res.ToObject<Payload>();
                ContextHelper.SetItem("account", Jresult.user_info.id.ToString());
                ContextHelper.SetItem("userId", Jresult.user_info.id.ToString());
                ContextHelper.SetItem("userName", Jresult.user_info.username);

                //return Success(Jresult["user_info"]);
            }
        }

        /// <summary>
        /// 返回请求信息
        /// </summary>
        /// <param name="response">返回头</param>
        /// <param name="data">数据</param>
        /// <returns></returns>
        private async Task RespondWithJson(HttpResponse response, object data)
        {
            response.StatusCode = 200;
            response.ContentType = "application/json;charset=utf-8";
            await response.WriteAsync(data.ToJson(), new UTF8Encoding(false));
        }
    }
}
